package com.wcpdoc.exam.core.service.impl;

import com.wcpdoc.base.cache.ProgressBarCache;
import com.wcpdoc.core.context.UserContext;
import com.wcpdoc.core.dao.BaseDao;
import com.wcpdoc.core.exception.MyException;
import com.wcpdoc.core.service.impl.BaseServiceImp;
import com.wcpdoc.core.util.BigDecimalUtil;
import com.wcpdoc.core.util.SpringUtil;
import com.wcpdoc.core.util.ValidateUtil;
import com.wcpdoc.exam.core.dao.MyMockQuestionDao;
import com.wcpdoc.exam.core.entity.*;
import com.wcpdoc.exam.core.entity.ex.MockExamQuestionEx;

import com.wcpdoc.exam.core.service.*;
import com.wcpdoc.exam.core.util.MockExamUtil;
import com.wcpdoc.exam.core.util.QuestionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 我的试题服务层实现
 * <p>
 * v1.0 zhanghc 2017-06-19 16:28:29
 */
@Service
public class MyMockQuestionServiceImpl extends BaseServiceImp<MyMockQuestion> implements MyMockQuestionService {
    private static final Logger log = LoggerFactory.getLogger(MyMockQuestionServiceImpl.class);
    @Resource
    private MyMockQuestionDao myQuestionDao;
    @Resource
    private MockExamQuestionService examQuestionService;
    @Resource
    private MyMockExamService myExamService;

    @Resource
    private MyMockQuestionService myMockQuestionService;

    @Resource
    private QuestionService questionService;

    @Resource
    private MockExamRuleService mockExamRuleService;

    @Resource
    private QuestionAnswerService questionAnswerService;

    @Override
    @Resource(name = "myMockQuestionDaoImpl")
    public void setDao(BaseDao<MyMockQuestion> dao) {
        super.dao = dao;
    }

    @Override
    public MyMockQuestion getMyQuestion(Integer examId, Integer userId, Integer questionId) {
        return myQuestionDao.getMyQuestion(examId, userId, questionId);
    }

    @Override
    public List<MyMockQuestion> getList(Integer examId, Integer userId) {
        return myQuestionDao.getList(examId, userId);
    }

    @Override
    public void clearMyMockExamQuestion(Integer examId, Integer userId) {
        myQuestionDao.clearMyMockExamQuestion(examId, userId);
    }

    @Override
    public void clear(Integer examId) {
        myQuestionDao.clear(examId);
    }

    @Override
    public void clearAnswer(Integer examId, Integer userId) {
        myQuestionDao.clearAnswer(examId, userId);
    }


    @Override
    public List<Map<String, Object>> getListUser(String id) {
        return null;
    }


    private BigDecimal[] splitScore(BigDecimal score, int num) {
        BigDecimal[] scores = new BigDecimal[num];
        BigDecimal singleScore = BigDecimalUtil.newInstance(score).div(num, 2).getResult();
        for (int i = 0; i < num - 1; i++) {
            scores[i] = singleScore;
        }
        scores[num - 1] = BigDecimalUtil.newInstance(singleScore).mul(num - 1).sub(score).mul(-1).getResult();
        return scores;
    }


    @Override
    public void genRandomList(Integer examId, Integer userId) {

        new Thread(new Runnable() {
            public void run() {

                try {
                    myMockQuestionService.clearMyMockExamQuestion(examId, userId);
                    List<MockExamRule> ruleList = mockExamRuleService.getList(examId);
                    System.out.println("ruleList==>" + ruleList);
//                    缓存题库
                    Map<Integer, List<Question>> questionListCache = new HashMap<>();

                    for (int i = 0; i < ruleList.size(); i++) {
                        MockExamRule examRule = ruleList.get(i);
                        if (!ValidateUtil.isValid(questionListCache.get(examRule.getQuestionTypeId()))) {
                            List<Question> questionList = questionService.getList(examRule.getQuestionTypeId());
                            questionListCache.put(examRule.getQuestionTypeId(), questionList);// 把题库缓存起来，用于模拟随机抽题
                        }
                    }
//                    重新生成my_mock_exam_question
                    Set<Question> questionOfUsed = new HashSet<>();
                    Map<Integer, List<QuestionAnswer>> questionAnswerCache = new HashMap<>();
                    int no = 1;
                    for (MockExamRule rule : ruleList) {

                        if (rule.getType() == 1) {
                            MyMockQuestion myMockQuestion = new MyMockQuestion();
                            myMockQuestion.setType(rule.getType());
                            myMockQuestion.setChapterName(rule.getChapterName());
                            myMockQuestion.setChapterTxt(rule.getChapterTxt());
                            myMockQuestion.setUserId(userId);
                            myMockQuestion.setExamId(examId);
                            myMockQuestion.setNo(no++);
                            myMockQuestionService.add(myMockQuestion);
                        } else {
                            List<Question> questionList = questionListCache.get(rule.getQuestionTypeId());
                            Collections.shuffle(questionList);// 从当前规则中随机抽题（乱序模拟随机）
                            Integer ruleRemainNum = rule.getNum();// 该规则试题数量，找到一个数量减一
                            for (Question question : questionList) {
                                if (ruleRemainNum <= 0) {// 满足规则，处理下一个规则
                                    break;
                                }
                                if (questionOfUsed.contains(question)) {// 已经使用过的试题就不能在用，继续找下一个
                                    continue;
                                }
                                if (rule.getQuestionType() != question.getType() // 当前试题不符合当前抽题规则，继续找下一个
                                        || rule.getMarkType() != question.getMarkType()) {
                                    continue;
                                }
                                MyMockQuestion myMockQuestion = new MyMockQuestion();
                                myMockQuestion.setType(rule.getType());
                                myMockQuestion.setScore(rule.getScore());
                                myMockQuestion.setMarkOptions(rule.getMarkOptions());
                                myMockQuestion.setQuestionId(question.getId());
                                myMockQuestion.setUserId(userId);
                                myMockQuestion.setExamId(examId);
                                myMockQuestion.setNo(no++); // 试题乱序无效，因为本身就是随机的
                                if (QuestionUtil.hasMultipleChoice(question)) {// 如果是多选，使用抽题规则的漏选分数
                                    myMockQuestion.setScores(rule.getScores());
                                } else if ((QuestionUtil.hasFillBlank(question) || QuestionUtil.hasQA(question)) // 如果是客观填空问答，把分数平均分配到子分数
                                        && QuestionUtil.hasObjective(question)) {// 如果抽题不设置分数，使用题库默认的分数，会导致总分不确定
                                    if (questionAnswerCache.get(myMockQuestion.getQuestionId()) == null) {// 如果抽题设置分数，主观题答案数量不一样，没法按答案分配分数
                                        questionAnswerCache.put(myMockQuestion.getQuestionId(),
                                                questionAnswerService.getList(myMockQuestion.getQuestionId()));
                                    }
                                    List<QuestionAnswer> questionAnswerList = questionAnswerCache.get(myMockQuestion.getQuestionId());// 所以规则为当题分数，平均分配到每个答案
                                    myMockQuestion.setScores(splitScore(rule.getScore(), questionAnswerList.size()));
                                }

                                myMockQuestion.setUpdateTime(new Date());
                                myMockQuestion.setUpdateUserId(userId);
                                myMockQuestionService.add(myMockQuestion);
                                questionOfUsed.add(question);
                                ruleRemainNum--;
                            }
                        }

                    }
                } catch (
                        MyException e) {
                    log.error("交卷后，重新随机生成错误：{}", e.getMessage());
                } catch (
                        Exception e) {
                    log.error("交卷后，重新随机生成错误：", e);
                }
              }
      }).start();

    }

}
